import hashlib
import numpy as np
from numpy.random import default_rng
import matplotlib.pyplot as plt

# 密钥流产生器
# PLM 映射函数
# num_segments：分段的段数，控制系统的混沌程度和分段的粒度。
def piecewise_logistic_map(x, r, num_segments,j):
    segment_length = 1.0 / num_segments
    # print(j)
    a = ""
    for i in range(num_segments):
        left_segment = i * segment_length
        right_segment = (i + 1) * segment_length
        if x > left_segment and  x < right_segment:
            if i % 2 == 0:
                x = num_segments * num_segments * r *(x - left_segment) * (right_segment - x)
            else:
                x = 1 - (num_segments * num_segments * r * (x - left_segment) * (right_segment - x))
            break
        elif x == i / num_segments and x != 1:
            x = x + 1.0 /(num_segments)
            break
        elif x == 1:
            x = x - 1.0 /(num_segments)
            break
    return x

# generate_key函数是生成密钥的函数，其参数包括：
# seed_str：种子值，用于初始化Logistic映射的状态值。
def generate_key_stream(x, r, num_segments, key_length):
    key = []
    print("x:"+str(x))
    for j in range(key_length):
        x = piecewise_logistic_map(x, r, num_segments,j)
        key.append(int(x * 10000) % 256) # 取最后两位小数作为密钥的一个字节
        # key.append(x)
    return key


def chaos_map(x, a=3.99):
    return np.mod(a * x * (1 - x), 1)

# 离散混沌映射随机数函数
def chaos_next(x,n):
    key = []
    for i in range(n):
        x = chaos_map(x)
        key.append(int(x * 10000) % 256)
        # key.append(x)
    return key

 
#  密钥获取hash函数
def key_to_hash(seed_str):
    # 计算字符串的哈希值
    sha256 = hashlib.sha256(seed_str.encode()).digest()
    # 使用哈希值作为种子
    rng = default_rng(int.from_bytes(sha256, "big"))
    # 生成随机数
    r = rng.random()
    # 保留两位小数
    r = np.round(r, decimals=2)
    # 输出结果
    return r

def showChart(data):
    # 计算概率分布
    counts, bins = np.histogram(data, bins=256)
    probs = counts / sum(counts) * 100

    # 绘制概率分布图
    plt.bar(bins[:-1], probs, width=1, alpha=0.7)

    plt.ylim([0, 8])
    # plt.yticks([0,0.1, 0.2, 0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0])
    plt.yticks([0,1,2,3,4,5,6,7,8])

    plt.xlim([0, 256])
    plt.xticks([0,25,50,75,100,125,150,175,200,225,250])

    # 添加标题和标签
    plt.title('chaos_and_logistic')
    plt.xlabel('Value')
    plt.ylabel('Probability (%)')

    # 显示图像
    plt.show()


# 异或运算
# key_stream_1,key_stream_2两个二进制字符串密钥流
def xor(key_stream_1,key_stream_2):
    key_stream = ""
    for i in range(len(key_stream_1)):
        if key_stream_1[i] == key_stream_2[i]:
            key_stream += "0"
        else:
            key_stream += "1"
    # print("key_stream_1:"+key_stream_1)
    # print("key_stream_2:"+key_stream_2)
    # print("key_stream:"+key_stream)
    return key_stream



if __name__ == '__main__':
    seed_str = "this is a key akk" #密钥key
    u = 3.98        #迭代状态值u->(0,4)
    n = 5            #映射的分段总数
    x = x = key_to_hash(seed_str)
    key_length = 50000  # key_length：生成的密钥长度，单位为字节
    key1 = generate_key_stream(x, u, n, key_length)
    key2 = chaos_next(x,key_length)
    key_arr1 = [format(pixel, '08b') for pixel in key1]
    key_arr2 = [format(pixel, '08b') for pixel in key2]
    result_str = []
    for i in range(len(key_arr1)):
        result_str.append(xor(key_arr1[i],key_arr2[i]))
    
    # # key_arr = [format(i, '03d') for i in key]
    # byte_arr1 = [bytearray(int(x[i:i+8], 2) for i in range(0, len(x), 8)) for x in key_arr1]
    # byte_arr2 = [bytearray(int(x[i:i+8], 2) for i in range(0, len(x), 8)) for x in key_arr2]

    # result = []
    # for i in range(len(byte_arr1)):
    #     xor_arr = bytes([byte_arr1[i][j] ^ byte_arr2[i][j] for j in range(len(byte_arr1[i]))])
    #     result.append(xor_arr)
    # 将结果转换为二进制字符串数组

    print(result_str)
    # print(byte_arr1)

    # data = [int(x,2) for x in result_str]

    # with open('bin_array.txt', 'w') as file:
    #     file.write(''.join(result_str))
   
    # 计算概率分布
    # print(data)
    # showChart(data)

    # print("key1 stream:",key_arr1)
    # print("key2 stream:",key_arr2)




   




